<template>
  <div class="bubble-background">
    <canvas ref="canvasRef"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'

const props = defineProps({
  config: {
    type: Object,
    default: () => ({
      count: 20,
      speed: 'slow',
      color: 'rainbow',
      size: 'large'
    })
  }
})

const canvasRef = ref(null)
let ctx = null
let bubbles = []
let animationId = null

class Bubble {
  constructor(canvas) {
    this.canvas = canvas
    this.reset()
    this.y = Math.random() * canvas.height
  }

  reset() {
    this.x = Math.random() * this.canvas.width
    this.y = this.canvas.height + 50
    this.size = this.getSize()
    this.speed = this.getSpeed()
    this.wobble = Math.random() * Math.PI * 2
    this.wobbleSpeed = Math.random() * 0.03 + 0.01
    this.color = this.getColor()
    this.opacity = Math.random() * 0.3 + 0.5
  }

  getSize() {
    const sizeMap = {
      small: Math.random() * 20 + 10,
      medium: Math.random() * 40 + 20,
      large: Math.random() * 60 + 30
    }
    return sizeMap[props.config.size] || sizeMap.medium
  }

  getSpeed() {
    const speedMap = {
      slow: Math.random() * 0.5 + 0.3,
      medium: Math.random() * 1 + 0.5,
      fast: Math.random() * 1.5 + 1
    }
    return speedMap[props.config.speed] || speedMap.medium
  }

  getColor() {
    if (props.config.color === 'rainbow') {
      const colors = ['#ff006e', '#fb5607', '#ffbe0b', '#8338ec', '#3a86ff', '#06ffa5']
      return colors[Math.floor(Math.random() * colors.length)]
    }
    return props.config.color
  }

  update() {
    this.y -= this.speed
    this.wobble += this.wobbleSpeed
    this.x += Math.sin(this.wobble) * 2

    if (this.y + this.size < 0) {
      this.reset()
    }
  }

  draw(context) {
    context.save()

    // 气泡外圈
    const gradient1 = context.createRadialGradient(
      this.x, this.y, 0,
      this.x, this.y, this.size
    )
    gradient1.addColorStop(0, this.color + 'cc')
    gradient1.addColorStop(0.7, this.color + '66')
    gradient1.addColorStop(1, this.color + '00')

    context.globalAlpha = this.opacity
    context.fillStyle = gradient1
    context.beginPath()
    context.arc(this.x, this.y, this.size, 0, Math.PI * 2)
    context.fill()

    // 气泡高光
    const highlightX = this.x - this.size * 0.3
    const highlightY = this.y - this.size * 0.3
    const gradient2 = context.createRadialGradient(
      highlightX, highlightY, 0,
      highlightX, highlightY, this.size * 0.5
    )
    gradient2.addColorStop(0, 'rgba(255, 255, 255, 0.8)')
    gradient2.addColorStop(1, 'rgba(255, 255, 255, 0)')

    context.fillStyle = gradient2
    context.beginPath()
    context.arc(highlightX, highlightY, this.size * 0.5, 0, Math.PI * 2)
    context.fill()

    context.restore()
  }
}

const init = () => {
  const canvas = canvasRef.value
  if (!canvas) return

  canvas.width = canvas.offsetWidth
  canvas.height = canvas.offsetHeight
  ctx = canvas.getContext('2d')

  bubbles = []
  for (let i = 0; i < props.config.count; i++) {
    bubbles.push(new Bubble(canvas))
  }
}

const animate = () => {
  if (!ctx || !canvasRef.value) return

  ctx.clearRect(0, 0, canvasRef.value.width, canvasRef.value.height)

  bubbles.forEach(bubble => {
    bubble.update()
    bubble.draw(ctx)
  })

  animationId = requestAnimationFrame(animate)
}

const handleResize = () => {
  init()
}

onMounted(() => {
  init()
  animate()
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  window.removeEventListener('resize', handleResize)
})

watch(() => props.config, () => {
  init()
}, { deep: true })
</script>

<style scoped>
.bubble-background {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background: linear-gradient(180deg, #e0f7fa 0%, #b2ebf2 50%, #80deea 100%);
}

canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
}
</style>

